//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package com.ruoyi.common.utils.jkalman.jama;

import com.ruoyi.common.utils.jkalman.jama.util.Maths;
import java.io.Serializable;

public class QRDecomposition implements Serializable {
    private double[][] QR;
    private int m;
    private int n;
    private double[] Rdiag;

    public QRDecomposition(Matrix A) {
        this.QR = A.getArrayCopy();
        this.m = A.getRowDimension();
        this.n = A.getColumnDimension();
        this.Rdiag = new double[this.n];

        for(int k = 0; k < this.n; ++k) {
            double nrm = 0.0;

            int j;
            for(j = k; j < this.m; ++j) {
                nrm = Maths.hypot(nrm, this.QR[j][k]);
            }

            if (nrm != 0.0) {
                if (this.QR[k][k] < 0.0) {
                    nrm = -nrm;
                }

                double[] var10000;
                for(j = k; j < this.m; ++j) {
                    var10000 = this.QR[j];
                    var10000[k] /= nrm;
                }

                double var10002 = this.QR[k][k]++;

                for(j = k + 1; j < this.n; ++j) {
                    double s = 0.0;

                    int i;
                    for(i = k; i < this.m; ++i) {
                        s += this.QR[i][k] * this.QR[i][j];
                    }

                    s = -s / this.QR[k][k];

                    for(i = k; i < this.m; ++i) {
                        var10000 = this.QR[i];
                        var10000[j] += s * this.QR[i][k];
                    }
                }
            }

            this.Rdiag[k] = -nrm;
        }

    }

    public boolean isFullRank() {
        for(int j = 0; j < this.n; ++j) {
            if (this.Rdiag[j] == 0.0) {
                return false;
            }
        }

        return true;
    }

    public Matrix getH() {
        Matrix X = new Matrix(this.m, this.n);
        double[][] H = X.getArray();

        for(int i = 0; i < this.m; ++i) {
            for(int j = 0; j < this.n; ++j) {
                if (i >= j) {
                    H[i][j] = this.QR[i][j];
                } else {
                    H[i][j] = 0.0;
                }
            }
        }

        return X;
    }

    public Matrix getR() {
        Matrix X = new Matrix(this.n, this.n);
        double[][] R = X.getArray();

        for(int i = 0; i < this.n; ++i) {
            for(int j = 0; j < this.n; ++j) {
                if (i < j) {
                    R[i][j] = this.QR[i][j];
                } else if (i == j) {
                    R[i][j] = this.Rdiag[i];
                } else {
                    R[i][j] = 0.0;
                }
            }
        }

        return X;
    }

    public Matrix getQ() {
        Matrix X = new Matrix(this.m, this.n);
        double[][] Q = X.getArray();

        for(int k = this.n - 1; k >= 0; --k) {
            int j;
            for(j = 0; j < this.m; ++j) {
                Q[j][k] = 0.0;
            }

            Q[k][k] = 1.0;

            for(j = k; j < this.n; ++j) {
                if (this.QR[k][k] != 0.0) {
                    double s = 0.0;

                    int i;
                    for(i = k; i < this.m; ++i) {
                        s += this.QR[i][k] * Q[i][j];
                    }

                    s = -s / this.QR[k][k];

                    for(i = k; i < this.m; ++i) {
                        Q[i][j] += s * this.QR[i][k];
                    }
                }
            }
        }

        return X;
    }

    public Matrix solve(Matrix B) {
        if (B.getRowDimension() != this.m) {
            throw new IllegalArgumentException("Matrix row dimensions must agree.");
        } else if (!this.isFullRank()) {
            throw new RuntimeException("Matrix is rank deficient.");
        } else {
            int nx = B.getColumnDimension();
            double[][] X = B.getArrayCopy();

            int k;
            int i;
            for(k = 0; k < this.n; ++k) {
                for(i = 0; i < nx; ++i) {
                    double s = 0.0;

                    int n;
                    for(n = k; n < this.m; ++n) {
                        s += this.QR[n][k] * X[n][n];
                    }

                    s = -s / this.QR[k][k];

                    for(i = k; i < this.m; ++i) {
                        X[i][i] += s * this.QR[i][k];
                    }
                }
            }

            for(k = this.n - 1; k >= 0; --k) {
                for(i = 0; i < nx; ++i) {
                    X[k][i] /= this.Rdiag[k];
                }

                for(i = 0; i < k; ++i) {
                    for(int j = 0; j < nx; ++j) {
                        X[i][j] -= X[k][j] * this.QR[i][k];
                    }
                }
            }

            return (new Matrix(X, this.n, nx)).getMatrix(0, this.n - 1, 0, nx - 1);
        }
    }
}
